#include"StdAfx.h"




pgRenderableObject::pgRenderableObject()
{
	m_pMesh = NULL;
	m_pMaterial = NULL;
	m_pConstantBuffer = NULL;

	m_worldTransformMatrix = pgMat44::Identity();
}

pgRenderableObject::pgRenderableObject(pgRenderableObject *pCopy)
{
	m_pMesh = new pgMesh();

	int idxCount = 0;
	m_pMesh->SetIndices(pCopy->m_pMesh->CopyIndices(idxCount), idxCount);
	m_pMesh->SetVertices(pCopy->m_pMesh->CopyVertices(idxCount), idxCount);

	m_pMaterial = new pgMaterial();
	m_pMaterial->SetDiffuse(pCopy->m_pMaterial->GetDiffuse());
	m_pMaterial->SetPixelShaderIndex(pCopy->m_pMaterial->GetPixelShaderIndex());
	m_pMaterial->SetVertexShaderIndex(pCopy->m_pMaterial->GetVertexShaderIndex());
}

pgRenderableObject::~pgRenderableObject()
{
	PG_SAFE_DELETE(m_pMesh);
	PG_SAFE_DELETE(m_pMaterial);
	PG_SAFE_RELEASE(m_pConstantBuffer);
}

bool pgRenderableObject::Load(const char* szFilePath)
{
	int isFBX = pgPath::GetExtension(szFilePath).compare("fbx");
	if (isFBX == 0)
		LoadFBX(szFilePath);
	else
	{
		LoadOBJ(szFilePath);
	}
	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	// Create the constant buffer
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof(ConstantBuffer);
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = 0;
    HRESULT hr = g_PG_pRenderer->m_pd3dDevice->CreateBuffer( &bd, NULL, &m_pConstantBuffer );

    if(FAILED( hr ))
	{
		PG_LOG_ERROR_SIMPLE("Failed to create constant buffer for pgPrimitiveTriangle!", hr);
        return false;
	}
	return true;
}


bool pgRenderableObject::LoadFBX(const char* szFilePath)
{
	pgRenderableObject *pCopy = pgFBXLoader::LoadMesh(szFilePath);

	m_pMesh = new pgMesh();

	if (pCopy->m_pMesh)
	{
		int idxCount = 0;
		m_pMesh->SetIndices(pCopy->m_pMesh->CopyIndices(idxCount), idxCount);
		m_pMesh->SetVertices(pCopy->m_pMesh->CopyVertices(idxCount), idxCount);
		}

	m_pMaterial = new pgMaterial();
	if (pCopy->m_pMaterial)
	{
		
		m_pMaterial->SetDiffuse(pCopy->m_pMaterial->GetDiffuse());
		m_pMaterial->SetPixelShaderIndex(pCopy->m_pMaterial->GetPixelShaderIndex());
		m_pMaterial->SetVertexShaderIndex(pCopy->m_pMaterial->GetVertexShaderIndex());
	}
	else
	{
		m_pMaterial->SetDiffuse(XMFLOAT3(1.0f, 1.0f, 1.0f));
		m_pMaterial->SetPixelShaderIndex(0);
		m_pMaterial->SetVertexShaderIndex(0);
	}

	delete pCopy;
	return true;
}

bool pgRenderableObject::LoadOBJ(const char* szFilePath)
{
	m_pMesh = pgOBJMeshLoader::LoadMesh(szFilePath);
	m_pMaterial = pgOBJMaterialLoader::LoadMaterial(pgPath::ChangeExtension(szFilePath, "mtl").c_str());

	return (m_pMesh != NULL && m_pMaterial != NULL);
}

 void pgRenderableObject::PreRender()
 {
	 m_pMesh->CreateBuffers();



	ID3D11InputLayout *pInputLayout = g_PG_pRenderer->GetVertexShader(0).GetVertexInputLayout();
	 g_PG_pRenderer->m_pImmediateContext->IASetInputLayout(pInputLayout);

	 UINT stride = sizeof(SVertex);
	 UINT offset = 0;

	 ID3D11Buffer *pVertBuf = m_pMesh->GetVertexBuffer();
	 ID3D11Buffer *pIndBuf = m_pMesh->GetIndexBuffer();

	 g_PG_pRenderer->m_pImmediateContext->IASetVertexBuffers(0, 1, &pVertBuf, &stride , &offset);

	 g_PG_pRenderer->m_pImmediateContext->IASetIndexBuffer(pIndBuf, DXGI_FORMAT_R16_UINT, 0);

	 g_PG_pRenderer->m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
 }

 void pgRenderableObject::Render()
{
	ConstantBuffer cb;
	cb.mWorld = XMMatrixTranspose(GetWorldTransformMatrix());
	cb.mView = XMMatrixTranspose( g_PG_pRenderer->GetViewCamera()->GetViewMatrix());
    cb.mProjection = XMMatrixTranspose( g_PG_pRenderer->GetViewCamera()->GetProjectionMatrix() );

	g_PG_pRenderer->m_pImmediateContext->UpdateSubresource( m_pConstantBuffer, 0, NULL, &cb, 0, 0 );

	g_PG_pRenderer->m_pImmediateContext->VSSetShader(g_PG_pRenderer->GetVertexShader(m_pMaterial->GetVertexShaderIndex()).GetVertexShader(), NULL, 0);

	g_PG_pRenderer->m_pImmediateContext->VSSetConstantBuffers(0,1, &m_pConstantBuffer);

	g_PG_pRenderer->m_pImmediateContext->PSSetShader(g_PG_pRenderer->GetPixelShader(m_pMaterial->GetPixelShaderIndex()).GetPixelShader(), NULL, 0);
	
	g_PG_pRenderer->m_pImmediateContext->DrawIndexed(m_pMesh->GetIndexCount(), 0, 0);
}

 void pgRenderableObject::PostRender()
 {
 }